﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media.Animation;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Text.RegularExpressions;
using Hugo.UIOptions;
using System.Windows.Media;

namespace Hugo
{
    public class NavigationPage : Canvas
    {
        List<UIOption> pageOptions;
        Dictionary<String, Rectangle> pageNameToIconMap;
        Dictionary<String, UIOption> pageNameToOptionMap;
        List<String> shiftNavigationPageNames;
        //List<String> otherNavigationPageNames;
        List<String> homeNavigationPageNames;
        List<String> nurseNavigationPageNames;
        List<String> backNavigationPageNames;

        HashSet<String> activeButtons;

        int controlsOffset = GlobalSettings.isRightHanded ? 170 : -170 - 3 * (ICON_BUFFER + GlobalSettings.ICON_WIDTH_SELECTED);

        int cursorCountDown;
       
        String selectedOptionName;
        Rectangle selectedRectangle;

        public const int ICON_BUFFER = 0;

        static int counter = 0;

        bool navigationComponentsVisible = true;

        private MainWindow MainWindow;

        private static NavigationPage instance;

        public static NavigationPage getInstance()
        {
            if (instance == null)
            {
                instance = new NavigationPage();
            }
            return instance;
        }

        private NavigationPage()
        {
            

            this.MainWindow = MainWindow.getInstance();

            pageOptions = new List<UIOption>();
            this.pageNameToIconMap = new Dictionary<String, Rectangle>();
            this.pageNameToOptionMap = new Dictionary<String, UIOption>();

            shiftNavigationPageNames = new List<string>();
            homeNavigationPageNames = new List<string>();
            nurseNavigationPageNames = new List<string>();
            backNavigationPageNames = new List<string>();

            addOptions();
        }

        private enum NavigationOptions { Left, Right, Nurse, Home, Back };

        private bool shiftNavigationsVisible = true;
        private bool homeNavigationVisible = true;
        private bool otherNavigationsVisible = true;
        private bool nurseNavigationVisible = true;
        private bool backNavigationVisible = true;


        public void setAllNavigationButtonsVisible(bool b)
        {
            shiftNavigationsVisible = b;
            homeNavigationVisible = b;
            nurseNavigationVisible = b;
            otherNavigationsVisible = b;
            backNavigationVisible = b;
        }

        public void setHomeNavigationButtonVisible(bool b)
        {
            homeNavigationVisible = b;
            foreach (String n in homeNavigationPageNames)
            {
                pageNameToIconMap[n].Opacity = b ? 1 : 0;
            }
        }

        public void setShiftNavigationsButtonVisible(bool b)
        {
            shiftNavigationsVisible = b;
            foreach (String n in shiftNavigationPageNames)
            {
                pageNameToIconMap[n].Opacity = b ? 1 : 0;
            }
        }

        public void setNurseNavigationButtonVisible(bool b)
        {
            nurseNavigationVisible = b;
            foreach (String n in nurseNavigationPageNames)
            {
                pageNameToIconMap[n].Opacity = b ? 1 : 0;
            }
        }

        public void setQuickNavigationButtonsVisible(bool b)
        {
            otherNavigationsVisible = b;
        }

        public void setBackNavigationButtonsVisible(bool b)
        {
            backNavigationVisible = b;
            foreach (String n in backNavigationPageNames)
            {
                pageNameToIconMap[n].Opacity = b ? 1 : 0; 
            }
        }

        public void updateButtonVisibility()
        {
            //TODO:fiume
            foreach (String n in shiftNavigationPageNames)
            {
                this.pageNameToIconMap[n].Opacity = 0;//this.shiftNavigationsVisible ? 1 : 0;
            }

            foreach (String n in homeNavigationPageNames)
            {
                this.pageNameToIconMap[n].Opacity = 0;// this.homeNavigationVisible ? 1 : 0;
            }

            foreach (String n in nurseNavigationPageNames)
            {
                this.pageNameToIconMap[n].Opacity = 0;//this.nurseNavigationVisible ? 1 : 0;
            }

            activeButtons = new HashSet<string>();

            /*if (this.shiftNavigationsVisible)
            {
                foreach (String n in shiftNavigationPageNames)
                {
                    activeButtons.Add(n);
                }
            }
             */

            /*
            if (this.otherNavigationsVisible)
            {
                foreach (String n in otherNavigationPageNames)
                {
                    if (homeNavigationPageNames.Contains(n)) { continue; }
                    activeButtons.Add(n);
                }
            }*/

            /*
            if (this.homeNavigationVisible)
            {
                foreach (String n in homeNavigationPageNames)
                {
                    activeButtons.Add(n);
                }
            }

            if (this.nurseNavigationVisible)
            {
                foreach (String n in nurseNavigationPageNames)
                {
                    activeButtons.Add(n);
                }
            }
             */

            if (this.backNavigationVisible)
            {
                foreach (String n in backNavigationPageNames)
                {
                    activeButtons.Add(n);
                }
            }
        }

        private void addOptions()
        {
            this.addNavigationUIOptions(new UINurseOption(), NavigationOptions.Nurse);
            this.addNavigationUIOptions(new TileUIPageShift(true), NavigationOptions.Left);
            this.addNavigationUIOptions(new TileUIPageShift(false), NavigationOptions.Right);
            this.addNavigationUIOptions(new HomeUIOption(), NavigationOptions.Home);
            this.addNavigationUIOptions(new BackUIOption(), NavigationOptions.Back);
        }

        /*
        public void setCursorPosition(System.Windows.Point p)
        {
            bool isOverSomething = false;

            foreach (String pageName in activeButtons)
            {

                Rectangle r = pageNameToIconMap[pageName];
                double rX = Canvas.GetLeft(r);// + currentpos;
                double rY = Canvas.GetTop(r);// -verticalBuffer;
                double rX2 = rX + r.ActualWidth;
                double rY2 = rY + r.ActualHeight;// +verticalBuffer * 2;

                if (rX < p.X && rY < p.Y && rX2 > p.X && rY2 > p.Y)
                {
                    isOverSomething = true;

                    if (selectedOptionName == null || !selectedOptionName.Equals(pageName))
                    {
                        Sounds.playSound(Sounds.Sound.Navigate);

                        selectedRectangle = r;
                        selectedOptionName = pageName;

                        HoldProgressIndicator.getInstance().setProgressLocation(new Point(Canvas.GetLeft(this.selectedRectangle), Canvas.GetTop(this.selectedRectangle)));
                        cursorCountDown = GlobalSettings.HOLD_TIME;
                    }

                    cursorCountDown--;

                    HoldProgressIndicator.getInstance().setProgressAmount(GlobalSettings.HOLD_TIME - cursorCountDown, GlobalSettings.HOLD_TIME);

                    if (cursorCountDown == 0)
                    {
                        pageNameToOptionMap[pageName].wasSelected();
                        selectedOptionName = null;
                    }
                }
            }

            if (!isOverSomething)
            {
                HoldProgressIndicator.getInstance().setProgressAmount(0, 1);
                selectedOptionName = null;
            }
        }
         */

        private int indexOfSelectedImage;

        public bool setCursorPosition(System.Windows.Point p)
        {
            bool isHovering = false;
            bool wasHovering = HandCursor.getInstance().isHovering();

            indexOfSelectedImage = getIndexOfImageAtPosition(p);
            
            if (indexOfSelectedImage != -1)
            {
                String optionName = pageOptions[indexOfSelectedImage].Name;

                if (activeButtons.Contains(optionName))
                {
                    isHovering = true;
                }
            }

            return isHovering;
        }

        private int getIndexOfImageAtPosition(Point p)
        {
            int index = -1;

            int i = 0;
            foreach (UIOption o in this.pageOptions)
            {
                Rectangle im = pageNameToIconMap[o.Name];

                Point pos = im.PointToScreen(new Point());

                double rX = pos.X - HandCursor.handSize / 2;
                double rY = pos.Y - HandCursor.handSize / 2;
                double rX2 = rX + im.ActualWidth;
                double rY2 = rY + im.ActualHeight;

                if (rX < p.X && rY < p.Y && rX2 > p.X && rY2 > p.Y)
                {
                    index = i;
                    break;
                }
                i++;
            }

            indexOfSelectedImage = index;

            return index;
        }

        private void addNavigationUIOptions(UIOption o, NavigationOptions which)
        {

            int middle = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width / 2;
            double navIconY = GlobalSettings.EffectiveScreenMiddleY + 280;

                this.pageOptions.Add(o);
                Rectangle rect = getSymbol(o.IconSource);

                rect.Width = o.IconSource.Width;
                rect.Height = o.IconSource.Height;

                rect.Name = "tileuinavpage" + (counter++) + "_rect";

                this.MainWindow.RegisterName(rect.Name, rect);
                MainWindow.getInstance().mainCanvas.Children.Add(rect);
                rect.Opacity = 1;
               
                    int bbuffer = 60;
                    controlsOffset = -(3 * GlobalSettings.ICON_WIDTH_SELECTED / 2 + bbuffer);

                    switch (which)
                    {
                        case NavigationOptions.Nurse:
                            Canvas.SetLeft(rect, GlobalSettings.EffectiveScreenMiddleX + GlobalSettings.ARMSPAN / 2 - GlobalSettings.ICON_WIDTH_SELECTED / 2 + GlobalSettings.ICON_WIDTH_SELECTED);
                            Canvas.SetTop(rect, navIconY+GlobalSettings.ICON_HEIGHT_SELECTED/2+10);
                            nurseNavigationPageNames.Add(o.Name);
                            break;
                        case NavigationOptions.Left:
                            Canvas.SetLeft(rect, GlobalSettings.EffectiveScreenMiddleX - GlobalSettings.ARMSPAN / 2 - GlobalSettings.ICON_WIDTH_SELECTED / 2);
                            Canvas.SetTop(rect, navIconY);
                            shiftNavigationPageNames.Add(o.Name);
                            break;
                        case NavigationOptions.Right:
                            Canvas.SetLeft(rect, GlobalSettings.EffectiveScreenMiddleX + GlobalSettings.ARMSPAN/2 - GlobalSettings.ICON_WIDTH_SELECTED/2);
                            Canvas.SetTop(rect, navIconY);
                            shiftNavigationPageNames.Add(o.Name);
                            break;
                        case NavigationOptions.Home:
                            Canvas.SetLeft(rect, GlobalSettings.EffectiveScreenMiddleX - GlobalSettings.ARMSPAN / 2 - GlobalSettings.ICON_WIDTH_SELECTED / 2 - GlobalSettings.ICON_WIDTH_SELECTED);
                            Canvas.SetTop(rect, navIconY + GlobalSettings.ICON_HEIGHT_SELECTED / 2 + 10);
                            homeNavigationPageNames.Add(o.Name);
                            break;
                        case NavigationOptions.Back:
                            Canvas.SetLeft(rect, GlobalSettings.EffectiveScreenMiddleX - rect.Width/2);
                            Canvas.SetTop(rect, navIconY);
                            backNavigationPageNames.Add(o.Name);
                            break;
                    }
                
                
                pageNameToIconMap.Add(o.Name, rect);
                pageNameToOptionMap.Add(o.Name, o);

        }

        public static Rectangle getSymbol(BitmapSource u)
        {
            return Util.getUnCenteredSymbol(u, GlobalSettings.ICON_WIDTH_SELECTED, GlobalSettings.ICON_HEIGHT_SELECTED);
        }

        public void setNavigationComponentsVisible(bool b)
        {
            this.navigationComponentsVisible = b;
            foreach (String pageName in pageNameToIconMap.Keys)
            {
                Rectangle r = pageNameToIconMap[pageName];
                if (b)
                {
                    r.Opacity = 1;
                }
                else
                {
                    r.Opacity = 0;
                }
            }
        }

        internal bool respondToKey(KeyEventArgs e)
        {
            
            if (e.Key == Key.Back)
            {
                MainWindow.popPage();
                return true;
            }

            return false;
        }


        internal bool respondToClick(MouseButtonEventArgs e)
        {

            //Point p = e.GetPosition(MainWindow.mainCanvas);
            //Console.WriteLine("Clicked at " + p.X + " " + p.Y);

            int indexOfImage = this.getIndexOfImageAtPosition(e.GetPosition(MainWindow.mainCanvas));

            if (indexOfImage == -1)
            {
                indexOfImage = pageOptions.Count - 1;
            }

            if (indexOfImage != -1)
            {
                Console.WriteLine("Clicked image " + indexOfImage);
                pageOptions[indexOfImage].wasSelected();
                return true;
            }
            else
            {
                Console.WriteLine("??? Can't get index");
            }

            return false;
        }
    }


}
